'''
Created on 2011-06-29

@author: Andrew Roth
'''
from collections import namedtuple

from bam_counter.counter import Counter

paired_row = namedtuple('PairedRow', ['ref', 'position', 'counts', 'depth'])

cdef class PairedBaseCounter(Counter):
    '''
    Class for iterating over positions from paired genome files counting bases.
    '''
    def __init__(self, Counter counter_1, Counter counter_2):
        self._counter_1 = counter_1
        self._counter_2 = counter_2
        
        self._refs = tuple(set(self._counter_1.refs) & set(self._counter_2.refs)) 
        
    def iter_ref(self, ref):
        if ref not in self.refs:
            raise Exception("Invalid reference passed.")
        
        return PairedBaseCounterIterator(
                                           ref,
                                           self._counter_1.iter_ref(ref),
                                           self._counter_2.iter_ref(ref)
                                         )

cdef class PairedBaseCounterIterator(CounterRefIterator):
    def __init__(self,
                 char * ref,
                 CounterRefIterator iter_1,
                 CounterRefIterator iter_2):
        
        self._ref = ref
        
        self._iter_1 = iter_1
        self._iter_2 = iter_2
        
        self._position = -1

    cdef cnext(self):
        cdef int pos_1, pos_2   
          
        self._iter_1.cnext()
        self._row_1 = self._iter_1._current_row
        
        self._iter_2.cnext()
        self._row_2 = self._iter_2._current_row
        
        while 1:
            pos_1 = self._row_1._position
            pos_2 = self._row_2._position
            
            if pos_1 == pos_2:
                self._position = pos_1
                       
                self._set_current_row()
                
                break   
            elif pos_1 < pos_2:
                self._iter_1.cnext()
                self._row_1 = self._iter_1._current_row
            elif pos_1 > pos_2:
                self._iter_2.cnext()
                self._row_2 = self._iter_2._current_row
            else:
                raise Exception("Error in joint pileup iterator.")

    cdef _set_current_row(self):        
        self._current_row = makePairedBaseCounterRow(self._ref, self._position, self._row_1.counts, self._row_2.counts)
    
cdef class PairedBaseCounterRow 
cdef PairedBaseCounterRow makePairedBaseCounterRow(char * ref, int position, tuple counts_1, tuple counts_2):
    cdef PairedBaseCounterRow row = PairedBaseCounterRow.__new__(PairedBaseCounterRow)
    
    row._ref = ref
    row._position = position
    
    row._counts_1 = counts_1
    row._counts_2 = counts_2

    return row
    
cdef class PairedBaseCounterRow(CounterRow):
    '''
    Class for storing binary count data from a pair of Bam files at a position.
    '''    
    def __init__(self):
        raise TypeError("This class cannot be instantiated from Python")
    
    property counts:
        def __get__(self):
            counts = []
            counts.extend(self._counts_1)
            counts.extend(self._counts_2)
            
            return tuple(counts)
    
    property depth:
        def __get__(self):
            cdef int depth_1
            cdef int depth_2
            
            depth_1 = sum(self._counts_1)
            depth_2 = sum(self._counts_2)
            
            if depth_1 < depth_2:
                return depth_1
            else:
                return depth_2